import asyncio
import time
import logging
import datetime

from tinyops.library.timer import Timer
from tinyops.config import Config
from tinyops.task import TaskQueue


LOG = logging.getLogger(__name__)


def format_timestamp(t):
    dt = datetime.datetime.utcfromtimestamp(t)
    return dt.isoformat()


class TimerState:
    def __init__(self, timer_config):
        self.name = timer_config.name
        self.task = timer_config.task
        self.timer = Timer(timer_config.timer)
        self.last_alerm = None


class TimerManager:
    def __init__(self, config: Config):
        self.config = config
        self.timers = []
        for timer_config in config.timers:
            timer_state = TimerState(timer_config)
            self.timers.append(timer_state)

    def main(self):
        with TaskQueue(self.config) as task_queue:
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)
            loop.create_task(self._async_main(loop, task_queue))
            loop.run_forever()

    async def _timer(self, timer_state: TimerState, task_queue: TaskQueue):
        timer_state.last_alerm = time.time()
        timer = timer_state.timer
        while True:
            now = time.time()
            next_alerm = timer.next(timer_state.last_alerm)
            if now < next_alerm:
                LOG.info(f'timer {timer_state.name} {format_timestamp(next_alerm)}')
                await asyncio.sleep(next_alerm - now)
            else:
                LOG.info(f'timer {timer_state.name} trigger task {timer_state.task}')
                timer_state.last_alerm = now
                task_queue.submit(timer_state.task)

    async def _async_main(self, loop, task_queue: TaskQueue):
        for timer_state in self.timers:
            timer = self._timer(timer_state, task_queue)
            loop.create_task(timer)
